package fl.ass.service.service.impl;

import cmm.service.core.framework.biz.BaseBizImpl;
import cmm.service.core.framework.dao.IBaseDao;
import cn.cmm.base.framework.constant.BaseConstant;
import cn.cmm.base.framework.exception.BaseException;
import cn.cmm.base.framework.logger.eum.LogExceptionEnum;
import cn.cmm.base.framework.utils.BaseLogUtils;
import cn.cmm.base.framework.utils.CollectionUtils;
import cn.cmm.base.framework.utils.DateUtils;
import cn.cmm.base.framework.utils.DecimalUtils;
import cn.fl.capital.condition.CapOverdueInfoQueryCondition;
import cn.fl.capital.constant.CapitalConstant;
import cn.fl.capital.dto.CapOverdueInfoDTO;
import cn.fl.capital.service.ICapOverdueInfoApiService;
import cn.fl.project.api.IPrjPaySchApiService;
import cn.fl.project.api.IPrjPrdDtlExtApiService;
import cn.fl.project.condition.PrjPrdDtlQueryCondition;
import cn.fl.project.condition.PrjPrdDtlSchRQC;
import cn.fl.project.condition.PrjPrdPaySchDQueryCondition;
import cn.fl.project.condition.PrjPrdPaySchMQueryCondition;
import cn.fl.project.constant.PrjPrdDtlConstant;
import cn.fl.project.constant.PrjPrdPaySchMConstant;
import cn.fl.project.dto.*;
import cn.fl.project.service.IPrjPrdPaySchMApiService;
import cn.fl.project.service.IProjectApiService;
import com.alibaba.fastjson.JSON;
import fl.ass.facade.condition.AssVfInfoQC;
import fl.ass.facade.constant.AssVfInfoConstant;
import fl.ass.facade.dto.AssVfInfoDTO;
import fl.ass.facade.dto.ProductStatusLogDTO;
import fl.ass.service.dao.AssVfInfoMapper;
import fl.ass.service.po.AssVfInfo;
import fl.ass.service.service.IAssTrailCarDService;
import fl.ass.service.service.IAssVfInfoService;
import fl.ass.service.transform.AssVfInfoTransform;
import fl.customer.facade.customer.api.ICustomerQueryApiService;
import fl.customer.facade.customer.dto.CstBscInfoDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;


/**
 * @Description: 资产核销信息表 服务层接口实现
 * @Description: 类中已经实现了简单增删改查操作, 可以直接使用, 如果有需要重写该方法即可：
 * @Description: 1、add(TVO entity) 2、removeById(Long id) 3、modify(DTO entity) 4、selectById(Long id)	5、searchListPage(Pager page) 7、searchList(DTO dto)
 * @Description: 业务层方法名称前缀：新增：add* 删除：remove* 修改：modify* 查询对象：select* get* 批量：batch* 查询集合：search*
 */
@Service
public class AssVfInfoServiceImpl extends BaseBizImpl<AssVfInfo, AssVfInfoDTO, AssVfInfoQC> implements IAssVfInfoService {

    @SuppressWarnings("unused")
    private static final Logger logger = LoggerFactory.getLogger(AssVfInfoServiceImpl.class);

    @Autowired
    private AssVfInfoMapper assVfInfoMapper;

    @Autowired
    private IPrjPrdPaySchMApiService prjPrdPaySchMApiService;

    @Autowired
    private ICapOverdueInfoApiService capOverdueInfoApiService;

    @Autowired
    private ICustomerQueryApiService customerQueryApiService;

    @Autowired
    private IPrjPaySchApiService prjPaySchApiService;

    @Autowired
    private IAssTrailCarDService assTrailCarDService;

    @Autowired
    private IPrjPrdDtlExtApiService prjPrdDtlExtApiService;

    @Autowired
    private IProjectApiService projectApiService;

    @Override
    public List<AssVfInfoDTO> searchList(AssVfInfoQC condition) throws BaseException {
        if (null == condition) return new ArrayList<AssVfInfoDTO>();
        List<AssVfInfo> list = this.assVfInfoMapper.selectList(condition);
        return AssVfInfoTransform.toDTOList(list);
    }

    @Override
    public IBaseDao<AssVfInfo, AssVfInfoQC> getDao() {
        return this.assVfInfoMapper;
    }


    @Override
    public boolean handlePaySchNosAndInsertVfInfo(List<String> paySchNoList, Long crtUsrId) throws BaseException {
        try {
            List<Long> paySchIds = new ArrayList<>(paySchNoList.size());
            for (String paySchNo : paySchNoList) {
                PrjPrdPaySchMQueryCondition prjPrdPaySchMQueryCondition = new PrjPrdPaySchMQueryCondition();
                prjPrdPaySchMQueryCondition.setPaySchNo(paySchNo);
                prjPrdPaySchMQueryCondition.setIsDel(BaseConstant.IS_YESNO_NO);
                // 查支付表id
                List<PrjPrdPaySchMDTO> prjPrdPaySchMDTOS = prjPrdPaySchMApiService.searchPrjPrdPaySchMList(prjPrdPaySchMQueryCondition);
                if (CollectionUtils.isNotEmpty(prjPrdPaySchMDTOS)) {
                    paySchIds.add(prjPrdPaySchMDTOS.get(0).getId());
                }
            }

            if (CollectionUtils.isNotEmpty(paySchIds)) {
                List<PrjPrdPaySchMDTO> list = new ArrayList<>(paySchIds.size());
                for (Long paySchId : paySchIds) {
                    // 查启用支付表
                    List<PrjPrdPaySchMDTO> enabledPrjPrdPaySchMDTO = prjPrdPaySchMApiService.selectEnabledListByPaySchId(paySchId);
                    if (CollectionUtils.isNotEmpty(enabledPrjPrdPaySchMDTO)) {
                        list.add(enabledPrjPrdPaySchMDTO.get(0));
                    }
                }
                for (PrjPrdPaySchMDTO prjPrdPaySchMDTO : list) {
                    AssVfInfoQC assVfInfoQC = new AssVfInfoQC();
                    assVfInfoQC.setPaySchNo(prjPrdPaySchMDTO.getPaySchNo());
                    List<AssVfInfo> assVfInfos = assVfInfoMapper.selectList(assVfInfoQC);
                    if (CollectionUtils.isNotEmpty(assVfInfos)) {
                        continue;
                    }
                    CstBscInfoDTO cstBscInfo = customerQueryApiService.getCstBscInfoById(prjPrdPaySchMDTO.getCstId());
                    PrjBscInfoDTO prjBscInfoDTO = projectApiService.selectById(prjPrdPaySchMDTO.getPrjId());
                    AssVfInfo info = new AssVfInfo();
                    info.setCstId(prjPrdPaySchMDTO.getCstId());
                    info.setCstNm(cstBscInfo.getCstNm());
                    info.setIdtyNum(cstBscInfo.getCertNo());
                    info.setCntNo(prjBscInfoDTO.getLsCntNo());
                    info.setPaySchId(prjPrdPaySchMDTO.getId());
                    info.setPaySchNo(prjPrdPaySchMDTO.getPaySchNo());
                    info.setPaySchStsCd(PrjPrdDtlConstant.CODE_PRJ_PRD_STS_CD_40);
                    info.setVfStsCd(AssVfInfoConstant.VF_STS_GRP_CD_1);
                    // 处理逾期数据以及核销金额
                    info = doOvdData(info, prjPrdPaySchMDTO);
                    info.setBreakAmt(getBreakAmt(prjPrdPaySchMDTO.getId()));
                    info.setCrtUsrId(crtUsrId);
                    // 添加一条资产核销数据
                    assVfInfoMapper.insert(info);
                    // 处理资产状态为已强制结清并迁出逾期任务
                    updatePrdStsCd(prjPrdPaySchMDTO.getId());
                    // 若启用支付表为SH或备份，则添加一条项目产品明细数据供征信使用
                    insertPrjPrdDtl4Credit(prjPrdPaySchMDTO);
                }
            }
            return true;
        } catch (BaseException e) {
            BaseLogUtils.newLogger("查询支付表及逾期数据并插入资产核销明细数据失败").setKeys("paySchNos:" + JSON.toJSONString(paySchNoList)).setThrowable(e).error(LogExceptionEnum.COMMON_CODE_0002);
            throw e;
        } catch (Exception e) {
            BaseLogUtils.newLogger("查询支付表及逾期数据并插入资产核销明细数据失败").setKeys("paySchNos:" + JSON.toJSONString(paySchNoList)).setThrowable(e).error(LogExceptionEnum.COMMON_CODE_0002);
            throw e;
        }
    }

    /**
     * 若启用支付表为SH或备份，则添加一条项目产品明细数据供征信使用
     * @param prjPrdPaySchMDTO
     */
    private void insertPrjPrdDtl4Credit(PrjPrdPaySchMDTO prjPrdPaySchMDTO) {
        PrjPrdDtlDTO dto = new PrjPrdDtlDTO();
        dto.setPaySchId(prjPrdPaySchMDTO.getId());
        dto.setStlDt(Calendar.getInstance().getTime());
        dto.setPrdStsCd(PrjPrdDtlConstant.CODE_PRJ_PRD_STS_CD_40);
        dto.setOpCode("OP0018");

        this.prjPrdDtlExtApiService.insertPrjPrdDtlWhenSettledBFAndSH(dto);
    }

    /**
     * 处理逾期数据和核销金额
     * @param info
     * @param prjPrdPaySchMDTO
     * @return
     */
    private AssVfInfo doOvdData(AssVfInfo info, PrjPrdPaySchMDTO prjPrdPaySchMDTO) {
        CapOverdueInfoQueryCondition capOverdueInfoQueryCondition = new CapOverdueInfoQueryCondition();
        capOverdueInfoQueryCondition.setPaySchId(prjPrdPaySchMDTO.getId());
        capOverdueInfoQueryCondition.setDataStatusCd(BaseConstant.IS_YESNO_NO_STR);
        capOverdueInfoQueryCondition.setIsDel(BaseConstant.IS_YESNO_NO);
        capOverdueInfoQueryCondition.setCstId(prjPrdPaySchMDTO.getCstId());
        List<CapOverdueInfoDTO> capOverdueInfoDTOS = capOverdueInfoApiService.searchCapOverdueInfoList(capOverdueInfoQueryCondition);
        CapOverdueInfoDTO capOverdueInfoDTO = null;
        if (CollectionUtils.isNotEmpty(capOverdueInfoDTOS)) {
            capOverdueInfoDTO = capOverdueInfoDTOS.get(0);
            info.setOvdDay(capOverdueInfoDTO.getOverdueDay());
            info.setOvdAmt(capOverdueInfoDTO.getOverdueAmount());
            info.setOvdRent(capOverdueInfoDTO.getOverdueInterest() + capOverdueInfoDTO.getOverduePrincipal());
            info.setOvdItr(capOverdueInfoDTO.getOverdueInterest());
            info.setOvdPntItr(capOverdueInfoDTO.getPenaltyAmount());
        }
        info.setVfAmt(getVfAmt(prjPrdPaySchMDTO.getId(), capOverdueInfoDTO));
        return info;
    }

    /**
     * 处理资产状态为已强制结清并迁出逾期任务
     * @param paySchId
     */
    private void updatePrdStsCd(Long paySchId) {
        PrjPrdDtlSchRQC prjPrdDtlSchRQC = new PrjPrdDtlSchRQC();
        prjPrdDtlSchRQC.setPaySchId(paySchId);
        List<PrjPrdDtlSchRDTO> prjPrdDtlSchRDTOS = prjPrdPaySchMApiService.searchDtlSchRList(prjPrdDtlSchRQC);
        if (CollectionUtils.isNotEmpty(prjPrdDtlSchRDTOS)) {
            for (PrjPrdDtlSchRDTO prjPrdDtlSchRDTO : prjPrdDtlSchRDTOS) {
                ProductStatusLogDTO productStatusLogDTO = new ProductStatusLogDTO();
                productStatusLogDTO.setPrjPrdId(prjPrdDtlSchRDTO.getPrjPrdDtlId());
                productStatusLogDTO.setCurrentStatus(PrjPrdDtlConstant.CODE_PRJ_PRD_STS_CD_40);
                productStatusLogDTO.setOpCode("OP0018");
                productStatusLogDTO.setProcessInstanceCode("资产核销");
                productStatusLogDTO.setProcessInstanceId("资产核销");
                List<ProductStatusLogDTO> statusDTOS = new ArrayList<>(1);
                statusDTOS.add(productStatusLogDTO);
                // 修改对应支付表状态为已强制结清并添加结清时间以及迁出逾期任务
                assTrailCarDService.updatePayStatus(statusDTOS);
            }
        }
    }

    private Long getVfAmt(Long paySchId, CapOverdueInfoDTO capOverdueInfoDTO) {
        // 逾期租金
        Long ovdRent = 0L;
        if (null != capOverdueInfoDTO) {
            ovdRent = capOverdueInfoDTO.getOverdueInterest() + capOverdueInfoDTO.getOverduePrincipal();
        }
        // 未来未还本金
        PrjPrdPaySchDQueryCondition prjPrdPaySchDQueryCondition = new PrjPrdPaySchDQueryCondition();
        prjPrdPaySchDQueryCondition.setPaySchId(paySchId);
        prjPrdPaySchDQueryCondition.setFeeTypCd(CapitalConstant.CODE_FEE_TYP_CD_S03);
        prjPrdPaySchDQueryCondition.setIsDel(BaseConstant.IS_YESNO_NO);
        prjPrdPaySchDQueryCondition.setPayDtMin(DateUtils.formatDateToString(Calendar.getInstance().getTime(), DateUtils.YYYY_MM_DD));
        List<PrjPrdPaySchDDTO> prjPrdPaySchDDTOS = prjPaySchApiService.searchList(prjPrdPaySchDQueryCondition);
        Long futureAmt = 0L;
        for (PrjPrdPaySchDDTO prjPrdPaySchDDTO : prjPrdPaySchDDTOS) {
            futureAmt += prjPrdPaySchDDTO.getArAmt();
        }
        // 保证金合计
        Long bondAmt = assVfInfoMapper.getBondAmt(paySchId);
        return ovdRent + futureAmt - bondAmt;
    }

    private Long getBreakAmt(Long paySchId) {
        PrjPrdPaySchDQueryCondition prjPrdPaySchDQueryCondition = new PrjPrdPaySchDQueryCondition();
        prjPrdPaySchDQueryCondition.setPaySchId(paySchId);
        prjPrdPaySchDQueryCondition.setFeeTypCd(CapitalConstant.CODE_FEE_TYP_CD_S01);
        prjPrdPaySchDQueryCondition.setIsDel(BaseConstant.IS_YESNO_NO);
        List<PrjPrdPaySchDDTO> prjPrdPaySchDDTOS = prjPaySchApiService.searchList(prjPrdPaySchDQueryCondition);
        Long breakAmt = 0L;
        for (PrjPrdPaySchDDTO prjPrdPaySchDDTO : prjPrdPaySchDDTOS) {
            breakAmt += Long.valueOf(String.valueOf(prjPrdPaySchDDTO.getFeeAmt()));
        }
        return Long.valueOf(String.valueOf(DecimalUtils.mul(Double.valueOf(String.valueOf(breakAmt)), 0.08d, 0)));
    }

}

